package com.um.weixin.pay.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.github.binarywang.wxpay.bean.ecommerce.PartnerTransactionsRequest;
import com.github.binarywang.wxpay.bean.ecommerce.RefundsRequest;
import com.github.binarywang.wxpay.bean.ecommerce.RefundsResult;
import com.github.binarywang.wxpay.bean.ecommerce.TransactionsResult;
import com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.um.springboot.starter.exception.ServiceException;
import com.um.weixin.pay.config.WxPayProperties;
import com.um.weixin.pay.service.WxPartnerPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;


/**
 * 微信支付(服务商版)
 * @author renjunwei
 * 日期 2023/11/8
 * 版权所有 广州优匠科技有限公司
 */
@Service
@Slf4j
public class WxPartnerPayServiceImpl implements WxPartnerPayService {

    @Autowired
    WxPayService wxPayService;

    @Autowired
    WxPayProperties wxPayProperties;

    /**
     * JSAPI下单
     *
     * @param outTradeNo
     * @param openId
     * @param amount
     * @param description
     * @param notifyUrl
     * @return
     * @throws WxPayException
     */
    @Override
    public TransactionsResult.JsapiResult createOrderByJsapi(String outTradeNo, String openId, Integer amount,
                                                             String description, String notifyUrl) throws WxPayException {
        return createOrderByJsapi(wxPayService.getConfig().getSubMchId(), outTradeNo, openId, amount, description,
                notifyUrl, true);
    }

    /**
     * JSAPI下单
     *
     * @param subMchid
     * @param outTradeNo
     * @param openId
     * @param amount
     * @param description
     * @param notifyUrl
     * @return
     * @throws WxPayException
     */
    @Override
    public TransactionsResult.JsapiResult createOrderByJsapi(String subMchid, String outTradeNo, String openId,
                                                             Integer amount, String description, String notifyUrl) throws WxPayException {
        return createOrderByJsapi(subMchid, outTradeNo, openId, amount, description, notifyUrl, true);
    }

    /**
     * JSAPI下单
     *
     * @param subMchid
     * @param outTradeNo
     * @param openId
     * @param payAmount
     * @param description
     * @param notifyUrl
     * @param isProfitSharing
     * @return
     * @throws WxPayException
     */
    @Override
    public TransactionsResult.JsapiResult createOrderByJsapi(String subMchid, String outTradeNo, String openId,
                                                             Integer payAmount, String description, String notifyUrl,
                                                             boolean isProfitSharing)  throws WxPayException  {
        Date timeExpire = DateUtil.date().offset(DateField.MINUTE, 30);
        return createOrderByJsapi(subMchid, outTradeNo, openId, payAmount, description, notifyUrl, isProfitSharing, timeExpire);
    }

    /**
     * JSAPI下单
     *
     * @param subMchid
     * @param outTradeNo
     * @param openId
     * @param payAmount
     * @param description
     * @param notifyUrl
     * @param isProfitSharing
     * @param timeExpire
     * @return
     * @throws WxPayException
     */
    @Override
    public TransactionsResult.JsapiResult createOrderByJsapi(String subMchid, String outTradeNo, String openId, Integer payAmount, String description, String notifyUrl, boolean isProfitSharing, Date timeExpire) throws WxPayException {
        PartnerTransactionsRequest.Amount amount = new PartnerTransactionsRequest.Amount();
        amount.setTotal(payAmount);

        PartnerTransactionsRequest.Payer payer = new PartnerTransactionsRequest.Payer();
        payer.setSpOpenid(openId);

        PartnerTransactionsRequest.SettleInfo settleInfo = new PartnerTransactionsRequest.SettleInfo();
        settleInfo.setProfitSharing(isProfitSharing);

        PartnerTransactionsRequest request = new PartnerTransactionsRequest();
        request.setSpAppid(wxPayProperties.getAppId());
        request.setSpMchid(wxPayProperties.getMchId());
        request.setSubMchid(subMchid);
        request.setDescription(description);
        request.setOutTradeNo(outTradeNo);
        request.setNotifyUrl(notifyUrl);
        request.setAmount(amount);
        request.setPayer(payer);
        request.setSettleInfo(settleInfo);
        if(null != timeExpire){
            request.setTimeExpire(DateUtil.format(timeExpire, DatePattern.UTC_WITH_XXX_OFFSET_PATTERN));
        }

        TransactionsResult result = null;
        try {
            result = wxPayService.getEcommerceService().partner(TradeTypeEnum.JSAPI, request);
        } catch (WxPayException e) {
            log.error("微信支付下单失败", e);
            throw new ServiceException("微信支付下单失败！");
        }
        TransactionsResult.JsapiResult jsapiResult = result.getPayInfo(TradeTypeEnum.JSAPI, request.getSpAppid(), request.getSpMchid(), wxPayService.getConfig().getPrivateKey());
        return jsapiResult;
    }

    /**
     * 退款
     * @param subMchId
     * @param outTradeNo
     * @param outRefundNo
     * @param payAmount
     * @param refundAmount
     * @return
     */
    @Override
    public WxPayRefundV3Result refundOrder(String subMchId, String outTradeNo, String outRefundNo, Integer payAmount, Integer refundAmount,
                                String reason, String notifyUrl) throws WxPayException {

        WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
        amount.setTotal(payAmount);
        amount.setRefund(refundAmount);
        amount.setCurrency("CNY"); //币种，目前仅仅支持"CNY"

        WxPayRefundV3Request request = new WxPayRefundV3Request();
        // request.setSpAppid(wxPayProperties.getAppId());
        request.setSubMchid(subMchId);
        request.setReason(reason);
        request.setOutTradeNo(outTradeNo);
        request.setOutRefundNo(outRefundNo);
        request.setNotifyUrl(notifyUrl);
        request.setAmount(amount);

        WxPayRefundV3Result refundsResult = wxPayService.refundV3(request);
        log.info("微信服务商申请退款结果：", JSONUtil.toJsonStr(refundsResult));
        return refundsResult;
    }


    /**
     * 退款
     * @param subMchId
     * @param outTradeNo
     * @param outRefundNo
     * @param payAmount
     * @param refundAmount
     * @return
     */
    @Override
    public WxPayRefundV3Result refundOrder(String subMchId, String outTradeNo, String transactionId, String outRefundNo, Integer payAmount, Integer refundAmount,
                                           String reason, String notifyUrl) throws WxPayException {

        WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
        amount.setTotal(payAmount);
        amount.setRefund(refundAmount);
        amount.setCurrency("CNY"); //币种，目前仅仅支持"CNY"

        WxPayRefundV3Request request = new WxPayRefundV3Request();
        // request.setSpAppid(wxPayProperties.getAppId());
        request.setSubMchid(subMchId);
        request.setTransactionId(transactionId);
        request.setReason(reason);
        request.setOutTradeNo(outTradeNo);
        request.setOutRefundNo(outRefundNo);
        request.setNotifyUrl(notifyUrl);
        request.setAmount(amount);

        WxPayRefundV3Result refundsResult = wxPayService.refundV3(request);
        log.info("微信服务商申请退款结果：", JSONUtil.toJsonStr(refundsResult));
        return refundsResult;
    }
}
